use std::ops::{Add, Div, Mul, Sub};
use num_traits::Num;

#[derive(Debug, Default)]
pub struct Value<T: Num> {
    pub data: T,
    prev: Vec<Value<T>>
}

impl<T: Num> Value<T> {
    pub fn new(data: T) -> Value<T> {
        Value { data }
    }
}

impl<T: Num> Add for Value<T> {
    type Output = Value<T>;

    fn add(self, rhs: Self) -> Self::Output {
        Value { data: self.data + rhs.data }
    }
}

impl<T: Num> Sub for Value<T> {
    type Output = Value<T>;

    fn sub(self, rhs: Self) -> Self::Output {
        Value { data: self.data - rhs.data }
    }
}

impl<T: Num> Mul for Value<T> {
    type Output = Value<T>;

    fn mul(self, rhs: Self) -> Self::Output {
        Value { data: self.data * rhs.data }
    }
}

impl<T: Num> Div for Value<T> {
    type Output = Value<T>;

    fn div(self, rhs: Self) -> Self::Output {
        Value { data: self.data / rhs.data }
    }
}




#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = Value::new(12.56);
        assert_eq!(result.data, 12.56);

        let a = Value::new(2.0);
        let b = Value::new(3.5);

        let result = a + b;

        assert_eq!(result.data, 5.5);

        let a = Value::new(2.0);
        let b = Value::new(-3.0);
        let c = Value::new(10.0);

        let result = a * b + c;

        assert_eq!(result.data, 4.0)
    }
}
